<?php

namespace App\Http\Utils\Integral;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * Class Crontab
 * @package App\Http\Utils\Integral
 */
class DayCrontab
{
    use UserContainer, ShopContainer;

    /**
     * 正常的天天积分红包任务
     */
    private function normalDayTasks()
    {
        DB::table('task')
            ->where([
                'type'    => 'day',
                'disable' => 'true',
                'enabled' => 'true',
            ])->where('count', '>', 0)
            ->orderBy('id')
            ->lockForUpdate()
            ->chunk(200, function ($values) {
                $values->map(function ($task) {
                    $role = json_decode($task->pistolgraph);
                    if ($role->day_every == 0) {
                        return;
                    }
                    $shop = $this->shop($task->shop_id);
                    if (!$shop->day_enabled) {
                        return;
                    }
                    $user = $this->user($task->user_id, $task->shop_id);
                    if (!$user->day_enabled) {
                        return;
                    }
                    if ($role->day_return - $task->grant_integral >= $role->day_every) {
                        $grant = $role->day_every;
                    } else {
                        $grant = $role->day_return - $task->grant_integral;
                    }
                    if ($shop->totalAmount > $grant) {
                        $user->flow($task->order_num, 'success', 'success', '天天积分红包', $grant, $task->id);
                        $shop->flow($task->order_num, $task->user_id, -$grant, '天天积分红包', $task->id);
                        DB::table('task')
                            ->where([
                                'id' => $task->id,
                            ])->update([
                                'count'          => $task->count - $grant,
                                'grant_integral' => $task->grant_integral + $grant,
                                'disable'        => 'true',
                                'update_time'    => Time::current(),
                            ]);
                    } else {
                        $user->flow($task->order_num, 'fail', '天天积分红包积分池积分不足', '天天积分红包', 0, $task->id);
                    }
                });
            });
    }

    /**
     * 补发天天积分红包
     */
    private function reissueDayTasks()
    {
        $users = DB::table('task')
            ->where([
                'type'           => 'luck',
                'grant_integral' => 0,
            ])->whereBetween('create_time', [
                strtotime(date('Y-m-d 00:00:00', strtotime("-1 day", Time::current()))),
                strtotime(date('Y-m-d 00:00:00', Time::current())),
            ])
            ->pluck('user_id')
            ->toArray();
        DB::table('task')
            ->where([
                'type'    => 'day',
                'disable' => 'false',
                'enabled' => 'true',
            ])->whereIn('user_id', $users)
            ->orderBy('id')
            ->lockForUpdate()
            ->chunk(200, function ($values) {
                $values->map(function ($task) {
                    $role = json_decode($task->pistolgraph);
                    if ($role->day_every == 0) {
                        return;
                    }
                    $shop = $this->shop($task->shop_id);
                    if (!$shop->day_enabled) {
                        return;
                    }
                    $user = $this->user($task->user_id, $task->shop_id);
                    if (!$user->day_enabled) {
                        return;
                    }
                    $need = $role->day_return % $role->day_every;
                    $grant = ($need == 0) ? $role->day_every : (($task->count <= 0) ? $need : $role->day_every);
                    if ($shop->totalAmount > $grant) {
                        $user->flow($task->order_num, 'success', 'success', '天天积分红包补发', $grant, $task->id);
                        $shop->flow($task->order_num, $task->user_id, -$grant, '天天积分红包补发', $task->id);
                        DB::table('task')
                            ->where([
                                'id' => $task->id,
                            ])->update([
                                'disable'           => 'true',
                                'unissued_integral' => $task->unissued_integral - $grant,
                                'update_time'       => Time::current(),
                            ]);
                    } else {
                        $user->flow($task->order_num, 'fail', '天天积分红包补发积分池积分不足', '天天积分红包补发', 0, $task->id);
                        DB::table('task')
                            ->where([
                                'id' => $task->id,
                            ])->update([
                                'count'             => $task->count + $grant,
                                'grant_integral'    => $task->grant_integral - $grant,
                                'unissued_integral' => $task->unissued_integral - $grant,
                                'disable'           => 'true',
                                'update_time'       => Time::current(),
                            ]);
                    }
                });
            });
    }

    /**
     * 手动积分任务
     */
    private function manualTasks()
    {
        DB::table('task')
            ->where([
                'type'    => 'manual',
                'disable' => 'true',
                'enabled' => 'true',
            ])->where('count', '>', 0)
            ->orderBy('id')
            ->lockForUpdate()
            ->chunk(100, function ($values) {
                $values->map(function ($task) {
                    $role = json_decode($task->pistolgraph);
                    if ($role->day_every == 0) {
                        return;
                    }
                    $shop = $this->shop($task->shop_id);
                    if (!$shop->mal_enabled) {
                        return;
                    }
                    $user = $this->user($task->user_id, $task->shop_id);
                    if (!$user->mal_enabled) {
                        return;
                    }
                    if ($role->day_return - $task->grant_integral >= $role->day_every) {
                        $grant = $role->day_every;
                    } else {
                        $grant = $role->day_return - $task->grant_integral;
                    }
                    if ($shop->totalAmount > $grant) {
                        $user->flow($task->order_num, 'success', 'success', '手动积分红包', $grant, $task->id);
                        $shop->flow($task->order_num, $task->user_id, -$grant, '手动积分红包', $task->id);
                        DB::table('task')
                            ->where([
                                'id' => $task->id,
                            ])->update([
                                'count'          => $task->count - $grant,
                                'grant_integral' => $task->grant_integral + $grant,
                                'disable'        => 'true',
                                'update_time'    => Time::current(),
                            ]);
                    } else {
                        $user->flow($task->order_num, 'fail', '手动积分红包积分池积分不足', '手动积分红包', 0, $task->id);
                    }
                });
            });
    }

    /**
     *
     */
    private function finish()
    {
        $this->shopRecord();
        $this->userRecord(true);
        DB::table('task')->where(['type' => 'luck'])
            ->where('create_time', '<', strtotime(date('Y-m-d 00:00:00', Time::current())))
            ->update([
                'disable'     => 'false',// 关闭幸运红包
                'update_time' => Time::current(),
            ]);
        DB::table('task')->where(['type' => 'day'])
            ->where('create_time', '<', strtotime(date('Y-m-d 00:00:00', Time::current())))
            ->update([
                'disable'     => 'true',// 标记所有天天红包为发放
                'update_time' => Time::current(),
            ]);
    }

    /**
     * @throws \Throwable
     */
    public function run()
    {
        DB::beginTransaction();
        try {
            $this->normalDayTasks();
            $this->reissueDayTasks();
            $this->manualTasks();
            $this->finish();
            DB::commit();
            Log::info("积分定时任务");
        } catch
        (\Throwable $throwable) {
            DB::rollBack();
            throw $throwable;
        }
    }
}